#ifndef __IM_MODULE_H__
#define __IM_MODULE_H__

#include <im_base_types.h>
#include <im_object.h>
#include <im_string.h>

/**
 * @defgroup IMModule
 * @ingroup PrivateIMBusIME
 * @{
 */

/** @struct IMModule
 *  @brief Class to load a dynamic linked module.
 */

IM_BEGIN_DECLS

#define IM_MODULE(p)             (IM_TYPE_INSTANCE_CHECK_CAST((p),IM_TYPE_MODULE,IMModule))
#define IM_CONST_MODULE(p)       (IM_TYPE_INSTANCE_CHECK_CAST_CONST((p),IM_TYPE_MODULE,IMModule))
#define IM_MODULE_CLASS(c)       (IM_TYPE_CLASS_CHECK_CAST((c),IM_TYPE_MODULE,IMModuleClass))
#define IM_IS_MODULE(p)          (IM_TYPE_INSTANCE_CHECK_TYPE((p),IM_TYPE_MODULE))
#define IM_IS_MODULE_CLASS(c)    (IM_TYPE_CLASS_CHECK_TYPE((c),IM_TYPE_MODULE))
#define IM_MODULE_GET_CLASS(p)   (IM_TYPE_INSTANCE_GET_CLASS_CAST((p),IM_TYPE_MODULE,IMModuleClass))

typedef struct _IMModule         IMModule;
typedef struct _IMModuleClass    IMModuleClass;

typedef IMBool  (*IMModuleInitFunc)             (IMModule           *module);
typedef void    (*IMModuleFinalizeFunc)         (IMModule           *module);

/**
 * @brief Open a module from shared library file.
 *
 * This method will open a shared library and return a pointer of this module.
 */
IMModule*       im_module_open                  (const IMChar       *file_name);

/**
 * @brief Closed opened module and release related resources
 *
 * This method will release module resources and close a shared library file.
 */
IMBool          im_module_close                 (IMModule           *module);

/**
 * @brief Verify a module
 *
 * This method will verify a module.
 */
IMBool          im_module_valid                 (const IMModule     *module);

/**
 * @brief Make a module resident
 *
 * This method will make a module resident: this module can not be closed.
 */
IMBool          im_module_make_resident         (IMModule           *module);

/**
 * @brief Check whether a module is resident
 *
 * This method will return if a module is resident.
 */
IMBool          im_module_is_resident           (IMModule           *module);

/**
 * @brief Look up a symbol by name
 *
 * This method will look up a symbol and return its pointer
 */
IMPointer       im_module_symbol                (const IMModule     *module,
                                                 const IMChar       *symbol_name);
/**
 * @brief Get module's file name
 *
 * This method will return module's filename
 */
const IMChar*   im_module_file_name             (const IMModule     *module);

/**
 * @brief Build module path
 *
 * This method will build a module path by directory and module_name.
 * TODO: is not implemented
 */
IMString*       im_module_build_path            (const IMChar       *directory,
                                                 const IMChar       *module_name);

/**
 * @brief Register a class type for a specified module.
 *
 * This method should be used inside module when calling im_module_init()
 * to register all class types for the module.
 *
 * A module should only use this method to register dynamic class types.
 */
IMType          im_module_register_type_class   (IMModule           *module,
                                                 IMType              parent,
                                                 const IMChar       *class_name,
                                                 const IMTypeInfo   *type_info,
                                                 IMBool              instantiatable);

/**
 * @brief Deregister a class type for a specified module.
 *
 * This method should be used inside module to deregister a dynamic
 * class type for this module.
 */
IMBool          im_module_deregister_type_class (IMModule           *module,
                                                 IMType              type);

IM_END_DECLS
/** @} */

#endif
/*
vi:ts=4:nowrap:ai:expandtab
*/
